from fastapi import FastAPI, Request, status
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
from sqlalchemy.exc import SQLAlchemyError
from typing import Union, Dict, Any, Optional
from pydantic import BaseModel
from datetime import datetime
from app.utils.log_config import get_logger
import traceback
import uuid

# 获取错误日志记录器
logger = get_logger("error")

# 定义统一的错误响应模型
class ErrorResponse(BaseModel):
    code: int
    message: str
    detail: Optional[str] = None
    error_type: str
    timestamp: str
    request_id: str
    path: Optional[str] = None

# 定义错误代码
class ErrorCode:
    # 系统级错误 (10000-19999)
    SYSTEM_ERROR = 10000
    DATABASE_ERROR = 10001
    EXTERNAL_SERVICE_ERROR = 10002
    
    # 业务级错误 (20000-29999)
    VALIDATION_ERROR = 20000
    RESOURCE_NOT_FOUND = 20001
    PERMISSION_DENIED = 20002
    
    # 数据处理错误 (30000-39999)
    DATA_PROCESSING_ERROR = 30000
    FILE_UPLOAD_ERROR = 30001
    DATA_FORMAT_ERROR = 30002

# 自定义异常基类
class APIException(Exception):
    def __init__(
        self,
        code: int,
        message: str,
        detail: str = None,
        error_type: str = None
    ):
        self.code = code
        self.message = message
        self.detail = detail
        self.error_type = error_type or self.__class__.__name__
        super().__init__(message)

# 文件上传异常
class FileUploadException(APIException):
    def __init__(self, message: str, detail: str = None):
        super().__init__(
            code=ErrorCode.FILE_UPLOAD_ERROR,
            message=message,
            detail=detail
        )

# 数据分析异常
class DataAnalysisException(APIException):
    def __init__(self, message: str, detail: str = None):
        super().__init__(
            code=ErrorCode.DATA_PROCESSING_ERROR,
            message=message,
            detail=detail
        )

# 数据库异常
class DatabaseException(APIException):
    def __init__(self, message: str, detail: str = None):
        super().__init__(
            code=ErrorCode.DATABASE_ERROR,
            message=message,
            detail=detail
        )

def create_error_response(
    request: Request,
    exc: Exception,
    code: int,
    message: str,
    detail: str = None,
    error_type: str = None,
    status_code: int = 500
) -> JSONResponse:
    """创建统一格式的错误响应"""
    # 生成唯一请求ID，便于跟踪问题
    request_id = getattr(request.state, "request_id", str(uuid.uuid4()))
    
    # 记录错误日志
    log_message = f"Error {code}: {message}"
    if detail:
        log_message += f" - Detail: {detail}"
    logger.error(f"{log_message} [RequestID: {request_id}, Path: {request.url.path}]")
    logger.error(f"Exception: {exc.__class__.__name__}: {str(exc)}")
    logger.debug(f"Traceback: {traceback.format_exc()}")
    
    # 构建错误响应
    error_response = ErrorResponse(
        code=code,
        message=message,
        detail=detail,
        error_type=error_type or exc.__class__.__name__,
        timestamp=datetime.now().isoformat(),
        request_id=request_id,
        path=request.url.path
    )
    
    return JSONResponse(
        status_code=status_code,
        content=error_response.dict(exclude_none=True)
    )

def setup_error_handlers(app: FastAPI):
    """设置全局错误处理器"""
    
    @app.exception_handler(APIException)
    async def api_exception_handler(request: Request, exc: APIException):
        return create_error_response(
            request=request,
            exc=exc,
            code=exc.code,
            message=exc.message,
            detail=exc.detail,
            error_type=exc.error_type,
            status_code=400
        )
    
    @app.exception_handler(RequestValidationError)
    async def validation_exception_handler(request: Request, exc: RequestValidationError):
        return create_error_response(
            request=request,
            exc=exc,
            code=ErrorCode.VALIDATION_ERROR,
            message="请求参数验证失败",
            detail=str(exc.errors()),
            status_code=422
        )
    
    @app.exception_handler(SQLAlchemyError)
    async def sqlalchemy_exception_handler(request: Request, exc: SQLAlchemyError):
        return create_error_response(
            request=request,
            exc=exc,
            code=ErrorCode.DATABASE_ERROR,
            message="数据库操作失败",
            detail=str(exc),
            status_code=500
        )
    
    @app.exception_handler(Exception)
    async def general_exception_handler(request: Request, exc: Exception):
        return create_error_response(
            request=request,
            exc=exc,
            code=ErrorCode.SYSTEM_ERROR,
            message="系统内部错误",
            detail=str(exc),
            status_code=500
        ) 